"""
https://leetcode.cn/problems/search-in-rotated-sorted-array/description/

33. 搜索旋转排序数组
已解答
中等
相关标签
相关企业
整数数组 nums 按升序排列，数组中的值 互不相同 。

在传递给函数之前，nums 在预先未知的某个下标 k（0 <= k < nums.length）上进行了 旋转，使数组变为 [nums[k], nums[k+1], ..., nums[n-1], nums[0], nums[1], ..., nums[k-1]]（下标 从 0 开始 计数）。例如， [0,1,2,4,5,6,7] 在下标 3 处经旋转后可能变为 [4,5,6,7,0,1,2] 。

给你 旋转后 的数组 nums 和一个整数 target ，如果 nums 中存在这个目标值 target ，则返回它的下标，否则返回 -1 。

你必须设计一个时间复杂度为 O(log n) 的算法解决此问题。

 

示例 1：

输入：nums = [4,5,6,7,0,1,2], target = 0
输出：4
示例 2：

输入：nums = [4,5,6,7,0,1,2], target = 3
输出：-1
示例 3：

输入：nums = [1], target = 0
输出：-1
 

提示：

1 <= nums.length <= 5000
-104 <= nums[i] <= 104
nums 中的每个值都 独一无二
题目数据保证 nums 在预先未知的某个下标上进行了旋转
-104 <= target <= 104

"""

from typing import List


class Solution:
    def search(self, nums: List[int], target: int) -> int:
        """
        寻找下标
        1. 先查询旋转最小值的开始索引
        2. 模拟中分查找
        """
        if len(nums)==1:
            return 0 if nums[0]==target else -1

        min_idx=0
        if nums[0]>nums[-1]:
            left,right=0,len(nums)-1
            while left+1<right:
                mid=(left+right)//2
                if nums[left]>nums[mid]:
                    right=mid
                else:
                    left=mid
            min_idx=right

        max_idx=min_idx+len(nums)-1
        if nums[min_idx]>target:
            return -1
        if nums[max_idx%len(nums)]<target:
            return -1

        left=min_idx
        right=max_idx+1
        # 左包右不包
        while left+1<right:
            mid=(left+right)//2
            mid_val=nums[mid%len(nums)]
            if mid_val==target:
                return mid%len(nums)
            elif mid_val>target:
                right=mid
            else:
                left=mid
        
        return left%len(nums) if nums[left%len(nums)]==target else -1

if __name__=='__main__':
    # 测试代码
    solution=Solution()
    nums=[3,5,1]
    target=4
    print(solution.search(nums,target)) 
    pass